package com.mq.mongo.service.impl;

import com.mq.common.utils.ReflectionUtils;
import com.mq.mongo.bean.MongoRepositoryMeta;
import com.mq.mongo.dao.BaseMongoDao;
import com.mq.mongo.service.IMongoService;
import com.mq.common.entity.EntiytList;
import com.mq.common.entity.page.Page;
import com.mq.utils.SpringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.util.Assert;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @version v1.0
 * @ClassName MongoService
 * @Description 基础mongo服务类
 */
public abstract class BaseMongoService<T,Mapper extends BaseMongoDao, ID extends Serializable> implements IMongoService<T, ID>{

    /**
     * 服务类对应的元数据
     */
    private MongoRepositoryMeta repositoryMeta = new MongoRepositoryMeta() {
        {
            BaseMongoService<T, Mapper,ID> srv = BaseMongoService.this;
            Class<? extends BaseMongoService> clazzType = srv.getClass();
            Class<Mapper> mtClassType = ReflectionUtils.getSuperClassGenricType(clazzType, 1);
            setMtClassType(mtClassType);
        }
    };

    private  volatile  Mapper mongoDao;

    @Override
    public T insert(T t) {
        return (T)getDao().insert(t);
    }

    @Override
    public  Collection<T> insertAll(Collection<? extends T> datas) {
        return (Collection<T>)getDao().insert(datas);
    }

    @Override
    public  T save(T t) {
        return (T)getDao().save(t);
    }

    @Override
    public void deleteByCondition(T t) {
        getDao().deleteByCondition(t);
    }

    @Override
    public boolean deleteById(ID id) {
       return getDao().deleteById(id);
    }

    @Override
    public boolean updateById(ID id, T t) { return getDao().updateById(id, t); }

    @Override
    public boolean updateById(ID id, Update update) {
       return getDao().updateById(id, update);
    }
    @Override
    public long update(Query query, Update update) {
        return getDao().update(query, update);
    }

    @Override
    public EntiytList findByPage(Page<T> page, Query query) {
        return getDao().findByPage(page,query);
    }

    @Override
    public List<T> findByCondition(T t) {
        return getDao().findByCondition(t);
    }

    @Override
    public List<T> find(Query query) {
        return getDao().find(query);
    }
    @Override
    public T findOne(Query query) { return (T) getDao().findOne(query); }

    @Override
    public T findById(ID id) {
        return (T) getDao().findById(id);
    }

    @Override
    public T findById(ID id, String collectionName) {
        return (T) getDao().findById(id, collectionName);
    }

    @Override
    public long count(Query query) {
        return getDao().count(query);
    }

    @Override
    public MongoTemplate getMongoTemplate() {
        return getDao().getMongoTemplate();
    }

    /**
     * 获取Dao实例
     */
    private BaseMongoDao getDao() {
        if (null == mongoDao) {
            synchronized (this.getClass().getName()) {
                if (null == mongoDao) {
                    mongoDao = (Mapper) getBaseDao();
                    Assert.notNull(mongoDao, "mongoDao instance not null");
                }
            }
        }
        return mongoDao;
    }


    /**
     * 获取BaseMongoDao实例
     * @return
     */
    private BaseMongoDao getBaseDao() {
        Class<Mapper> mtClassType = repositoryMeta.getMtClassType();
        return SpringUtils.getBean(mtClassType);
    }
}
